# -*- encoding: utf-8 -*-

# Copyright 2010 István Szentandrási
# <etude-music-player@googlegroups.com>

# This file is part of Etude.
#
# Etude is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as 
# published by the Free Software Foundation, either version 3 
# of the License, or (at your option) any later version.
#
# Etude is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with Etude. If not, see <http://www.gnu.org/licenses/>.

from . import _
import threading
import modules
import sys
import traceback

STATUS_FOUND = 1
STATUS_NOT_FOUND = 2
STATUS_STARTING = 3

default_priority=["lastfm"]

class QueryItem:
    def __init__(self, id, artist, album):
        self.id = id
        self.artist = artist
        self.album = album

class QueryThread:
    def __init__(self, name, engine):
        self.name = name
        self.engine = engine

    def thread_function(self,status_func):
        self.status_func = status_func
        #Thread function starting
        while self.engine.should_run():
            item = self.engine.queue_pop()
            if not item:
                break
            item.status = self.status_func # set the func
            self.engine.do_item(item)
            item.status = None

class QueryEngine:
    
    def __init__(self, source_priority=default_priority):
        self.queue = []
        self.threads = []
        self.run = True
        self.lock = threading.Lock()
        self.cond = threading.Condition()
        self.source_prio = []
        self.modules = {}
        for module in modules.queriers:
            self.modules[module.shortName] = module
        for s in source_priority:
            if self.modules.has_key(s):
                self.source_prio.append(self.modules[s])
    
    def start(self, threadobj, threads=2, parent=None):
        for i in range(threads):
            if not parent:
                t = threadobj(str(i), self)
            else:
                t = threadobj(str(i), self, parent)
            t.daemon = True
            t.start()
            self.threads.append(t)
    
    def should_run(self):
        self.cond.acquire()
        ret = self.run
        self.cond.release()
        return ret
    
    def queue_push(self, item):
        if not isinstance(item, QueryItem):
            raise ValueError("queue_push() only want's CoverItems")
        self.cond.acquire()
        self.queue.append(item)
        self.cond.notify()
        self.cond.release()
    
    def queue_pop(self):
        i = None
        self.cond.acquire()
        while not i:
            if len(self.queue) > 0:
                i = self.queue.pop()
            else:
                self.cond.wait()
        self.cond.release()
        return i

    def do_item(self, item):
        list = []
        for q in self.source_prio:
            item.status(item, STATUS_STARTING, q.shortName)
            try:
                r = q.process(item)
                if r:
                    list += r
            except Exception, e:
                traceback.print_exception(*(sys.exc_info()))

        if len(list) > 0:
            item.status(item, STATUS_FOUND, list)
        else:
            item.status(item, STATUS_NOT_FOUND)

    def stop(self):
        self.run = False
        self.cond.acquire()
        self.cond.notifyAll()
        self.cond.release()

